#include "chatdialog.h"

#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QListWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QDateTime>
#include <QTimer>
#include "chatmessageitem.h"
#include "timeseparatoritem.h"

ChatDialog::ChatDialog(const QString &userName, QWidget *parent)
    : QDialog(parent)
    , m_userName(userName)
    , m_peer(nullptr)
    , m_listView(new QListWidget(this))
    , m_inputEdit(new QLineEdit(this))
    , m_sendButton(new QPushButton(tr("发送"), this))
    , m_inactivityTimer(new QTimer(this))
    , m_shouldShowNextTime(false)
{
    setWindowTitle(userName);
    resize(520, 520);
    m_listView->setUniformItemSizes(false);
    m_listView->setResizeMode(QListView::Adjust);
    m_listView->setWordWrap(true);
    m_listView->setSpacing(6);

    auto *mainLayout = new QVBoxLayout(this);
    mainLayout->addWidget(m_listView);

    auto *bottomLayout = new QHBoxLayout();
    bottomLayout->addWidget(m_inputEdit);
    bottomLayout->addWidget(m_sendButton);
    mainLayout->addLayout(bottomLayout);

    connect(m_sendButton, &QPushButton::clicked, this, &ChatDialog::handleSend);
    connect(m_inputEdit, &QLineEdit::returnPressed, this, &ChatDialog::handleSend);

    m_inactivityTimer->setSingleShot(true);
    m_inactivityTimer->setInterval(2 * 60 * 1000); // 2 minutes
    connect(m_inactivityTimer, &QTimer::timeout, [this]() {
        m_shouldShowNextTime = true;
    });
}

void ChatDialog::setPeer(ChatDialog *peerDialog)
{
    if (m_peer == peerDialog) return;
    if (m_peer) {
        disconnect(this, &ChatDialog::outgoingMessage, m_peer, &ChatDialog::receiveMessage);
    }
    m_peer = peerDialog;
    if (m_peer) {
        connect(this, &ChatDialog::outgoingMessage, m_peer, &ChatDialog::receiveMessage);
    }
}

void ChatDialog::handleSend()
{
    const QString text = m_inputEdit->text().trimmed();
    if (text.isEmpty()) return;

    maybeInsertTimeSeparator();
    appendMessageBubble(true, m_userName, text);

    // emit to peer
    emit outgoingMessage(m_userName, text);

    m_inputEdit->clear();
    m_inactivityTimer->start();
}

void ChatDialog::receiveMessage(const QString &senderName, const QString &messageText)
{
    maybeInsertTimeSeparator();
    appendMessageBubble(false, senderName, messageText);
    m_inactivityTimer->start();
}

void ChatDialog::appendMessageBubble(bool isSelf, const QString &name, const QString &text)
{
    auto *widget = new ChatMessageItem(isSelf ? ChatMessageItem::SelfSide : ChatMessageItem::PeerSide,
                                       name, text);
    auto *item = new QListWidgetItem(m_listView);
    item->setSizeHint(widget->sizeHint());
    m_listView->addItem(item);
    m_listView->setItemWidget(item, widget);
    m_listView->scrollToBottom();
}

void ChatDialog::maybeInsertTimeSeparator()
{
    if (!m_shouldShowNextTime) return;
    const QString nowStr = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm");
    auto *widget = new TimeSeparatorItem(nowStr, this);
    auto *item = new QListWidgetItem(m_listView);
    item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
    item->setSizeHint(widget->sizeHint());
    m_listView->addItem(item);
    m_listView->setItemWidget(item, widget);
    m_shouldShowNextTime = false;
}


